#include "scan_gobang.h"
#include "ui_scan_gobang.h"
#include "welcome.h"
#include "ui_welcome.h"

scan_gobang::scan_gobang(Gobang_Network *g_network, QWidget *parent) : QMainWindow(parent),
                                                                       ui(new Ui::scan_gobang)
{
    ui->setupUi(this);

    this->g_network = g_network;

    /* 实例chess */
    m_chess = new Chess();

    m_chessAi = new chessAi();

    /* 服务器给我列表 */
    connect(g_network->t, SIGNAL(rx_string(QString)),
            this, SLOT(rx_string(QString)));
    /* 绑定接收对方下棋 信号槽 */
    connect(g_network->t, SIGNAL(rx_pos_xy(uint8_t, uint8_t, char)),
            this, SLOT(rx_pos_xy(uint8_t, uint8_t, char)));
    /* 绑定接收颜色 信号槽 */
    connect(g_network->t, SIGNAL(rx_color(char)),
            this, SLOT(rx_color(char)));

    /* 初始化用户信息 */
    //    init_user_info(g_network);

    /* 定时器 */
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, [=]()
            {
       if(playtime != 0) {
           playtime--;
           ui->playtime->setText("倒计时：" + QString::number(playtime));
       } else {
           /* 随机下棋 */
           int rand_x, rand_y;
            do {
                rand_x = rand()%BUFF_SIZE;
                rand_y = rand()%BUFF_SIZE;
            }
            while(m_chess->check_chess(rand_x, rand_y));
            log("随机下棋：%d %d ", rand_x, rand_y);
            m_chess->add_chess(rand_x, rand_y, ChessStatus);
            g_network->tellOpponent_chassxy(static_cast<uint8_t>(rand_x),static_cast<uint8_t>(rand_y),ChessStatus);
            playStatus = false;
            timer->stop();
       } });

    /* 窗口初始化 */
    init_window();

    paint = new QPainter;

    // choose_color();

    //    init_input();

    /* 初始化时绑定信号槽连接 */
    init_button_clicked();

    this->clear_chess();
}

void scan_gobang::create_room()
{
    this->show();

    this->my_iden = master;
}

void scan_gobang::join_room()
{
    if (this->my_iden == master)
    {
        /* 有人进房间，解除棋盘 */
        this->playStatus = true;

        this->choose_color();
        g_network->tellOpponent_color(ChessStatus);
        return;
    }

    this->my_iden = guest;
    this->show();
}

// void scan_gobang::init_user_info(Gobang_Network *gobang_network)
//{

//}

void scan_gobang::init_window()
{
    setWindowTitle("五子棋");
    // QIcon icon;
    // icon.addFile(QStringLiteral("../../images/logo.png"), QSize(), QIcon::Normal, QIcon::Off);
    // setWindowIcon(icon);
}
void scan_gobang::init_input()
{
    lineEdit = new QLineEdit(this);
    lineEdit->setGeometry(QRect(width() - 300, height() - ButtonHeight, ButtonWidth, ButtonHeight));
    lineEdit->setEchoMode(QLineEdit::Normal);
    /* 设置提示 */
    lineEdit->setPlaceholderText("请输入发送内容");

    /* 发送按钮 */
    QPushButton *ok = new QPushButton("发送", this);
    ok->setGeometry(QRect(width() - 300, height() - ButtonHeight * 2, ButtonWidth, ButtonHeight));

    /* 连接信号槽 */
}
/*
 * 按键连接信号槽
 * @param null
 */
void scan_gobang::init_button_clicked()
{
    /* 绑定发送按键 */
    connect(ui->send, &QPushButton::clicked, this, &scan_gobang::send_message);

    connect(ui->chear, &QPushButton::clicked, this, &scan_gobang::undo_move);

    connect(g_network->t, &tcp::rx_undo, this, &scan_gobang::rx_undo_move);

    connect(g_network->t, SIGNAL(rx_undo_state(uint8_t)),
                this, SLOT(rx_undo_state(uint8_t)));

    connect(this->m_chessAi, SIGNAL(ai_signals(int, int)),
                this, SLOT(ai_slots(int, int)));
    connect(this->m_chessAi, &chessAi::kill_user, this, &scan_gobang::kill_user);
}

void scan_gobang::kill_user()
{
    QString ai[]={
        "运筹帷幄之中",
        "我已经赢了，你再下也是徒劳",
        "找到杀棋",
        "小小人类，拿捏拿捏",
        "你被最强ai打败，不丢人不丢人",
    };

    int num = QRandomGenerator::global()->bounded(4);		//生成一个0和10之间的整数

    this->my_printf("智能AI", ai[num]);
}

/*
 * 画棋子
 * @param x:棋子横坐标
 * @param y:棋子纵坐标
 * @param color:棋子颜色
 */
void scan_gobang::draw_chess(int x, int y, char color)
{
    /* 设置棋子填充颜色 */
    QColor brushColor = (color == Chessblack) ? Qt::black : Qt::white;
    /* 毛刷：颜色，实图案 */
    paint->setBrush(QBrush(brushColor, Qt::SolidPattern));

    /* 设置棋子边缘颜色 */
    QPen pen;
    pen.setWidth(WIDTH / 15);    // 边缘宽度
    pen.setColor(Qt::lightGray); // 黑色边缘
    paint->setPen(pen);

    /* 画椭圆：中心点X,Y,宽度，高度 */
    paint->drawEllipse((this->padding + x * WIDTH - WIDTH / 4),
                       (this->padding + y * WIDTH - WIDTH / 4),
                       WIDTH / 2,
                       WIDTH / 2);
}
/*
 * 棋子刷新
 * @param null
 */
void scan_gobang::update_chess()
{
    chess_t *temp = m_chess->chess_head->next;
    while (temp != m_chess->chess_head)
    {

        draw_chess(temp->x, temp->y, temp->color);
        temp = temp->next;
    }
}
bool scan_gobang::check_line(int start_i, int start_j, int dir_i, int dir_j, ChessType color)
{
    for (int k = 0; k < 5; k++)
    {
        int ni = start_i + k * dir_i;
        int nj = start_j + k * dir_j;
        if (ni < 0 || nj < 0 || ni >= CHASS_NUM || nj >= CHASS_NUM || !m_chess->check_chess_color(ni, nj, color))
        {
            return false;
        }
    }
    return true;
}
/*
 * 判断胜负
 * @param color:棋子颜色
 */
void scan_gobang::win_or_lose(ChessType color)
{

    chess_t *temp = m_chess->chess_head->next;
    while (temp != m_chess->chess_head)
    {

        if (temp->color == color)
        {
            // 只检查当前行、列和对角线
            if ((temp->y <= CHASS_NUM - 5 && check_line(temp->x, temp->y, 0, 1, color)) ||                             // 横向
                (temp->x <= CHASS_NUM - 5 && check_line(temp->x, temp->y, 1, 0, color)) ||                             // 纵向
                (temp->x <= CHASS_NUM - 5 && temp->y <= CHASS_NUM - 5 && check_line(temp->x, temp->y, 1, 1, color)) || // 左斜
                (temp->x <= CHASS_NUM - 5 && temp->y >= 4 && check_line(temp->x, temp->y, 1, -1, color)))
            { // 右斜
                QString chess_temp = (color == Chessblack) ? "黑棋" : "白棋";
                QMessageBox::information(this, "游戏结束！", "恭喜" + chess_temp + "，赢了！");
                // 清除棋盘 和停止定时器
                clear_chess();
                m_chessAi->init_tuple6type();
                playtime_down();
                return;
            }
        }

        temp = temp->next;
    }
}

/*
 * 清空棋盘
 * @param null
 */
void scan_gobang::clear_chess()
{
    m_chess->del_allchess();
}

void scan_gobang::rx_undo_state(uint8_t state)
{
    /* 同意 */
    if (state == 1) {
        QMessageBox::information(this, "悔棋", "对方同意悔棋！");

        /* 清除上一个棋子 */
        m_chess->del_lastone_chess();

        /* 更新下棋状态，开启下棋时间 */
        playStatus = true;
        playtime_up();

        /* 更新棋盘 */
        update();
    }
    /* 不同意 */
    else
    {
        QMessageBox::information(this, "对不起", "对方拒绝悔棋！");
    }
}

void scan_gobang::ai_slots(int x, int y)
{
    m_chess->add_chess(x, y, static_cast<ChessType>(ChessStatus * -1) );
    playStatus = true;
    playtime_up();
    win_or_lose(static_cast<ChessType>(ChessStatus * -1));
}

/*
 * 将要下的棋子,跟着鼠标移动
 */
void scan_gobang::draw_mouse()
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::NoPen));
    /* 判断1和-1 1：黑棋，-1：白棋 */
    painter.setBrush(ChessStatus == 1 ? Qt::black : (ChessStatus == -1 ? Qt::white : Qt::transparent));

    QPoint globalPos = QCursor::pos();
    QPoint localPos = mapFromGlobal(globalPos);

    /* 计算鼠标位置对应的棋盘交叉点 */
    int x = (localPos.x() - padding + WIDTH / 2) / WIDTH;
    int y = (localPos.y() - padding + WIDTH / 2) / WIDTH;

    // log("鼠标位置：%d,%d",x,y);

    /* 判断当下坐标有没有棋子 */
    if (m_chess->check_chess(x, y))
    {
        return;
    }

    /* 确保在棋盘范围内 */
    if (x >= 0 && x < CHASS_NUM && y >= 0 && y < CHASS_NUM)
    {
        /* 计算交叉点的中心位置 */
        QPoint center(padding + x * WIDTH, padding + y * WIDTH);

        /* 绘制圆形，作为下一个棋子的预览 */
        painter.drawEllipse(center, WIDTH / 4, WIDTH / 4);
    }
}

/*
 * 上一次下的棋子，在棋子周围画个红色框框
 */
void scan_gobang::draw_last_chess()
{
    chess_t *temp = m_chess->get_last_chess();
    if (temp != nullptr)
    {
        QPainter painter(this);
        painter.setPen(QPen(Qt::red, WIDTH / 15));
        painter.setBrush(Qt::NoBrush);

        // 计算矩形的大小和位置
        int rectSize = WIDTH / 2;
        int centerX = padding + temp->x * WIDTH;
        int centerY = padding + temp->y * WIDTH;

        // 绘制矩形框框
        QRect rect(centerX - rectSize / 2, centerY - rectSize / 2, rectSize, rectSize);
        painter.drawRect(rect);
    }
}

void scan_gobang::updata_ui_size()
{
    ui->verticalLayoutWidget_2->setGeometry(QRect(chess_width, padding, this->width() - chess_width - padding, this->height() - padding * 2));

    ui->textEdit->setPlaceholderText("请输入发送内容");
    ui->textEdit->setFixedHeight(40);

    /* 显示当前时间 */
    // ui->playtime->setText( QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") );

    // 更新显示状态
    if (playStatus)
    {
        ui->playStatus->setText(ChessStatus == 1 ? "黑棋下" : "白棋下");
    }
    else
    {
        // gameMode == PVP ? (ChessStatus == -1 ? "轮到黑棋" : "轮到白棋") : (ChessStatus == -1 ? "轮到黑棋" : "轮到AI下棋")
        // 
        ui->playStatus->setText(gmode == PVP ? (ChessStatus == -1 ? "轮到黑棋" : "轮到白棋") : (ChessStatus == -1 ? "轮到黑棋" : "轮到AI下棋"));
    }
}

void scan_gobang::paintEvent(QPaintEvent *)
{
    /* 窗口拖动 */
    window_changed();

    /* 刷新ui布局 */
    updata_ui_size();

    /* 主窗口 */
    paint->begin(this);

    /* 画棋盘 */
    draw_chessboard();

    /* 更新棋子 */
    update_chess();

    /* 绘制上一个下棋棋子 */
    draw_last_chess();

    /* 更新鼠标 */
    draw_mouse();

    paint->end();
    // qDebug("paintEvent width:%d", width());

    update();
}
void scan_gobang::close_game()
{
    log("触发关闭游戏");
    clear_chess();
    this->signals_close_game();
}

void scan_gobang::closeEvent(QCloseEvent *event)
{
    int result = QMessageBox::information(this, tr("提示"), tr("你真的要退出游戏吗?"), tr("是的"), tr("不是"), 0, 1);

    if (result == 0)
    {
        this->close_game();
    }
    else
    {
        /* 忽略关闭事件 */
        event->ignore();
    }

    err("%d", result);
}
/*
 * 窗口大小改变响应函数
 * 高度不能大于宽度的1.5倍
 */
void scan_gobang::window_changed()
{
    setMinimumSize(QSize(MIN_WIDTH, MIN_WIDTH / 1.5));
    int new_width = std::max(width(), MIN_WIDTH);

    if (height() > new_width * 2 / 3)
    {
        resize(new_width, new_width * 2 / 3);
    }

    WIDTH = (std::min(width(), height()) - padding * 2) / BUFF_SIZE;
    chess_width = WIDTH * BUFF_SIZE + padding * 2;
}

/*
 * 画棋盘
 */
void scan_gobang::draw_chessboard()
{
    /* 钢笔工具：颜色，线号，实线 */
    paint->setPen(QPen(Qt::darkGreen, 2, Qt::SolidLine));

    for (int i = 0; i < BUFF_SIZE + 1; i++)
    {

        /* 画线函数：x1,y1,x2,y2:画从(x1,y1)到(x2,y2)的线 */
        paint->drawLine(padding, padding + WIDTH * i, padding + WIDTH * (BUFF_SIZE), padding + WIDTH * i);
    }
    /* 画BUFF_SIZE+1条竖线 */
    for (int i = 0; i < BUFF_SIZE + 1; i++)
    {
        paint->drawLine(padding + WIDTH * i, padding, padding + WIDTH * i, padding + WIDTH * (BUFF_SIZE));
    }
}

void scan_gobang::mousePressEvent(QMouseEvent *event)
{
    /* 检查是否为左键双击以及当前是否为玩家回合 */
    if (event->type() != QEvent::MouseButtonDblClick ||
        event->button() != Qt::LeftButton ||
        !playStatus)
    {
        return;
    }

    QPoint pos = event->pos();

    /* 检查点击是否在棋盘范围内 */
    int boardWidth = WIDTH * BUFF_SIZE;
    if (!QRect(padding, padding, boardWidth, boardWidth).contains(pos))
    {
        return;
    }

    /* 计算棋盘坐标 */
    int chess_x = qBound(0, (pos.x() - padding + WIDTH / 2) / WIDTH, BUFF_SIZE);
    int chess_y = qBound(0, (pos.y() - padding + WIDTH / 2) / WIDTH, BUFF_SIZE);

    /* 如果该位置已有棋子，则返回 */
    if (m_chess->check_chess(chess_x, chess_y))
    {
        return;
    }

    /* 放置棋子并更新状态 */
    m_chess->add_chess(chess_x, chess_y, ChessStatus);

    playStatus = false;

    /* debug 评估 */

//    EVALUATION modf = m_chessAi->evaluate(m_chessAi->chesses);
//    log("分数：%d", modf.score);


    update();

    if (gmode == PVP)
    {
        /* 通知对手并处理倒计时 */
        g_network->tellOpponent_chassxy(static_cast<uint8_t>(chess_x), static_cast<uint8_t>(chess_y), ChessStatus);

        playtime_down();

        /* 判断胜负并更新视图 */
        win_or_lose(ChessStatus);
        if (m_chess->get_last_chess() == nullptr) playStatus = true;
    }
    else
    {
        win_or_lose(ChessStatus);

        /* 如果棋盘还有棋子，说明游戏还在继续，调用人机下棋 */
        if (m_chess->get_last_chess() != nullptr)
        {
            /* ai下棋 */
            chessOneByAi();
        }
        else
        {
            playStatus = true;
        }
    }
}

void scan_gobang::mouseReleaseEvent(QMouseEvent *event)
{
    event->button();
    qDebug("鼠标移动响应函数");
}

/*
 * 悔棋
 */
void scan_gobang::undo_move()
{
    chess_t *temp = m_chess->get_last_chess();
    qDebug(" 悔棋 ");
    if (temp->color != ChessStatus)
    {
        QMessageBox::information(this, "不好意思", "不能悔棋两步哦！");
        return;
    }

    /* 发送悔棋请求。。。 */
    g_network->tellOpponent_undo();

    playStatus = false;
}

/*
 * 选择棋子颜色
 * 弹出选择对话框
 */
void scan_gobang::choose_color()
{
    /*
    QMessageBox msgBox;
    msgBox.setText("选择棋子颜色: Yes黑棋 & No白棋");
    msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msgBox.setDefaultButton(QMessageBox::Yes);
    int ret = msgBox.exec();

    if (ret == QMessageBox::Yes)
    {
        setChessStatus(Chessblack);
        qDebug("选择黑棋");
    }
    else if (ret == QMessageBox::No)
    {
        setChessStatus(Chesswhite);
        qDebug("选择白棋");
        qDebug() << g_network->link_state;
    }
    */

    int iBtn = QMessageBox::information(this, "提示", "请选择棋子颜色", "白子", "黑子", 0, 1);
    switch (iBtn) {
    case 0:
        setChessStatus(Chesswhite);
        qDebug("选择白棋");
       break;
    case 1:
        setChessStatus(Chessblack);
        qDebug("选择黑棋");
       break;
    default:
       break;
    }

    update();
}

void scan_gobang::aigameinit()
{
    this->show();
    this->setgamemode(PVC);
    this->playStatus = true;
    m_chessAi->init_tuple6type();
    this->choose_color();
}

void scan_gobang::chessOneByAi()
{
    chess_t *temp = m_chess->chess_head->next;
    while (temp != m_chess->chess_head)
    {
        m_chessAi->chesses[temp->x][temp->y] = (temp->color == Chessblack) ? C_BLACK : C_WHITE;
        temp = temp->next;
    }

    /* 开启ai下棋线程 */
    m_chessAi->start();

}

void scan_gobang::my_printf(QString obj, QString strTxtEdt)
{
    /* 读取输入框内容 */
    QString temp_string = QString(obj + "[%1]: %2 \n").arg(QTime::currentTime().toString("hh:mm:ss")).arg(strTxtEdt);

    /* 拼接发送内容 */
    textBrowser_string += temp_string;

    /* 发送消息 */
    /*
     * net code:
     */

    /* 显示到textBrowser */
    ui->textBrowser->setText(textBrowser_string);
}
void scan_gobang::send_message()
{

    QString strTxtEdt = ui->textEdit->toPlainText();
    if (!strTxtEdt.isEmpty() && gmode == PVP)
    {

        uint8_t state = g_network->tellOpponent_string(strTxtEdt.toUtf8().data(), strTxtEdt.toUtf8().length());
        log("发送的长度:%d", strTxtEdt.toUtf8().length());

        if (!state)
        {
            this->my_printf("我", strTxtEdt);
        }
        else
        {
            this->my_printf("未成功发送：我", strTxtEdt);
        }

        /* debug */
        if (strTxtEdt == "1")
        {
            playStatus = !playStatus;
        }
        if (strTxtEdt == "2")
        {
            chessOneByAi();
        }
        /* 清空输入框 */
        ui->textEdit->clear();
    }

    update();
}

void scan_gobang::playtime_up()
{
    /* 在playtime显示时间倒计时，限时90s */
    timer->stop();
    playtime = 30;
    timer->start(1000); // 每隔1秒触发一次
}

void scan_gobang::playtime_down()
{
    timer->stop();
    ui->playtime->clear();
}

void scan_gobang::mouseMoveEvent(QMouseEvent *event)
{
    event->button();
    qDebug("鼠标移动响应函数");
}

/*
 * 设置棋子状态
 * @param color:棋子颜色
 */
void scan_gobang::setChessStatus(char color)
{
    this->ChessStatus = static_cast<ChessType>(color);
}

/*
 * 设置游戏模式
 * @param gamemode:游戏模式
 */
void scan_gobang::setgamemode(GameMode_e gamemode)
{
    this->gmode = gamemode;
    (gamemode == PVC) ? qDebug("人机模式") : qDebug("玩家模式");
}

scan_gobang::~scan_gobang()
{
    err("gobang已被删除");
    delete ui;
}

void scan_gobang::rx_string(QString str)
{
    qDebug() << "收到数据:" << str;
    this->my_printf("那个他", str);
}
void scan_gobang::rx_pos_xy(uint8_t x, uint8_t y, char color)
{
    if ( gmode == PVP)
    {
        log("rx_pos_xy : color:%d", color);

        m_chess->add_chess(x, y, static_cast<ChessType>(color));

        playStatus = true;

        playtime_up();
        /*
         * 判断胜负
         */
        win_or_lose(static_cast<ChessType>(ChessStatus * -1));
        /* 对面赢了 */
        if (m_chess->get_last_chess() == nullptr) playStatus = false;
        update();
    }
}
void scan_gobang::rx_color(char color)
{
    this->setChessStatus(color * -1);
    playStatus = false;
}
/*
 * 接受悔棋
 */
void scan_gobang::rx_undo_move()
{
    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "悔棋", "是否同意悔棋？", QMessageBox::Yes | QMessageBox::No);

    uint8_t yes_no = 1;

    if (reply == QMessageBox::Yes)
    {
        /*  同意悔棋 */
        qDebug() << "同意悔棋";
        /* 清掉最后一步的棋子 */
        m_chess->del_lastone_chess();

        /* 对方下棋状态，更新下棋时间 */
        playStatus = false;
        playtime_down();
        update();
    }
    else
    {
        // 不同意悔棋的逻辑
        qDebug() << "不同意悔棋";
        yes_no = 0;
    }

    this->g_network->tellOpponent_undo_state(yes_no);
}
